#include <screenw.h>
#include <QDebug>
#include <QFile>
#include <labelbtn.h>
#include <QPixmap>
#include <supportfuncs.h>


CScreenW::CScreenW()
{
	setupUi( this );	
}


void CScreenW::Initialize()
{
	int i;
	int x, y;
	QWidget *pTab;
	QImage image;

		
	m_pLblScreen = new CLabelBtn( m_pFrmScreen, 32*16, 24*16 );
	m_pLblScreen->setGeometry( 3, 3, 32*16, 24*16 );
	m_pLblScreen->show();

	connect( m_pLblScreen, SIGNAL( onClickedLeft( int, int ) ), this, SLOT( OnScreenClick( int, int ) ) );
	
	m_pTabBank = new QTabWidget( this );
	m_pTabBank->setGeometry( QRect( 5, 410, 596, 184 ) );
	
	for( i = 0; i < 3; i++ )
	{
		pTab = new QWidget();
		m_pTabBank->addTab( pTab, QString());
		m_pTabBank->setTabText( m_pTabBank->indexOf( pTab), QString( "Bank %1" ).arg( i ) );
		
		m_pFrmBank[i] = new QFrame( pTab );
		m_pFrmBank[i]->setGeometry( QRect( 5, 10, 591, 194) );
		m_pFrmBank[i]->setFrameShape( QFrame::StyledPanel );
		m_pFrmBank[i]->setFrameShadow( QFrame::Raised );

		m_pLblBank[i] = new CLabelBtn( m_pFrmBank[i], 32*18, 8*18 );
		m_pLblBank[i]->setGeometry( 0, 0, m_pFrmBank[i]->width(), m_pFrmBank[i]->height() );
		
		m_pLblBank[i]->show();
	}
	
	connect( m_pTabBank, SIGNAL( currentChanged( int ) ), this, SLOT( OnBankChanged( int ) ) );
	
	connect( m_pLblBank[0], SIGNAL( onClickedLeft( int, int ) ), this, SLOT( OnBank0Click( int, int ) ) );
	connect( m_pLblBank[1], SIGNAL( onClickedLeft( int, int ) ), this, SLOT( OnBank1Click( int, int ) ) );
	connect( m_pLblBank[2], SIGNAL( onClickedLeft( int, int ) ), this, SLOT( OnBank2Click( int, int ) ) );
		
	m_pLblPalette = new CLabelBtn( m_pFrmPalette, 40, 96 );
	m_pLblPalette->setGeometry( 0, 0, m_pFrmPalette->width(), m_pFrmPalette->height() );

	connect( m_pLblPalette, SIGNAL( onClickedLeft( int, int ) ), this, SLOT( OnPaletteClick( int, int ) ) );

	m_pLblTile = new CLabelBtn( m_pFrmTile, 96, 96 );
	m_pLblTile->setGeometry( 2, 2, m_pFrmTile->width(), m_pFrmTile->height() );
	
	connect( m_pLblTile, SIGNAL( onClickedLeft( int, int ) ), this, SLOT( OnTileClickLeft( int, int ) ) );
	connect( m_pLblTile, SIGNAL( onClickedRight( int, int ) ), this, SLOT( OnTileClickRight( int, int ) ) );
	
	m_pLblColors = new CLabelBtn( m_pFrmColors, 96, 12 );
	m_pLblColors->setGeometry( 3, 3, 12*16, 16 );
	
	image = QImage( m_pLblColors->width(), m_pLblColors->height(), QImage::Format_RGB32 );
	
	for( x = 0; x < 16; x++ ) CSupportFuncs::SetPixelRect( &image, x*12, 0, CSupportFuncs::COLORS_TABLE[x], 12, 16 );
	
	m_pLblColors->put_Image( image );
	
	connect( m_pLblColors, SIGNAL( onClickedLeft( int, int ) ), this, SLOT( OnColorsClick( int, int ) ) );

	connect( m_pBtnFromBank, SIGNAL( clicked() ), this, SLOT( OnFromBank() ) );
	connect( m_pBtnToBank, SIGNAL( clicked() ), this, SLOT( OnToBank() ) );

	connect( m_pRadBack, SIGNAL( clicked() ), this, SLOT( OnRadBack() ) );
	connect( m_pRadFore, SIGNAL( clicked() ), this, SLOT( OnRadFore() ) );
	
	m_SelColor = QPoint( 1, 0 );
	
	for( x = 0; x < 256*3; x++ ) m_Screen[x] = 0;
	for( y = 0; y < 3; y++ ) for( x = 0; x < 256; x++ )	m_TilesBank[x][y] = CTile();
	
	m_pRadFore->setChecked( true );
	m_Close = false;
}

void CScreenW::UpdateBank( int tile, int bank, bool updateScreen )
{
	PaintTile( &m_BankImages[bank], m_TilesBank[tile][bank], (tile%32)*18+1, (tile/32)*18+1, 2 );

	m_pLblBank[bank]->put_Image( m_BankImages[bank] ); 
	
	if( updateScreen ) UpdateScreen();
}

void CScreenW::InitBanks()
{
	int i, j;
	
	
	for( j = 0; j < 3; j++ ) 
	{
		m_BankImages[j] = m_pLblBank[j]->pixmap()->toImage();

		PaintGrid( &m_BankImages[j], 16, 16 );

		for( i = 0; i < 256; i++ ) 
		{
			PaintTile( &m_BankImages[j], m_TilesBank[i][j], (i%32)*18+1, (i/32)*18+1, 2 );
		}

		m_pLblBank[j]->put_Image( m_BankImages[j] );
	}

	UpdateScreen();
	
	OnBank0Click( 1, 1 );
}

void CScreenW::UpdateScreen()
{
	int i;
	int row, col;
	QImage image;
	
	
	image = QImage( 32*16, 24*16, QImage::Format_RGB32 );
	
	for( i = 0; i < 3; i++ )
	{
		for( row = 0; row < 8; row++ )
		{
			for( col = 0; col < 32; col++ )
			{
				PaintTile( &image, m_TilesBank[ m_Screen[(i*8+row)*32+col] ][ i ], col*16, (i*8+row)*16, 2 );
			}
		}
	}
	m_pLblScreen->put_Image( image );
}


void CScreenW::OnBank0Click( int x, int y )
{
	OnBankClick( x, y, 0 );
}

void CScreenW::OnBank1Click( int x, int y )
{
	OnBankClick( x, y, 1 );
}

void CScreenW::OnBank2Click( int x, int y )
{
	OnBankClick( x, y, 2 );
}

void CScreenW::OnBankClick( int x, int y, int bank )
{
	CSupportFuncs::SetBorderImage( &m_BankImages[m_SelTile.y()], (m_SelTile.x()%32)*18 + 1, (m_SelTile.x()/32)*18 + 1, 16, 16, 0xC0C0C0 );
	m_pLblBank[m_SelTile.y()]->put_Image( m_BankImages[m_SelTile.y()] );
	
	m_SelTile = QPoint( (y/18)*32+(x/18), bank );
	CSupportFuncs::SetBorderImage( &m_BankImages[bank], (m_SelTile.x()%32)*18 + 1, (m_SelTile.x()/32)*18 + 1, 16, 16, 0xffff00 );
	m_pLblBank[bank]->put_Image( m_BankImages[bank] );
	
	m_pLblShowTile->setText( QString( "%1" ).arg( m_SelTile.x() ) );
}

void CScreenW::OnPaletteClick( int x, int y )
{
	m_SelColor = QPoint( x/(int)20, y/(int)12 );

	if( m_SelColor.x() == 0 ) m_pRadBack->click();
	else m_pRadFore->click();
}


void CScreenW::OnColorsClick( int x, int y )
{
	int c;
	
	
	c = x / 12;

	if( m_SelColor.x() == 0 ) m_TileDesign.SetBackColor( m_SelColor.y(), c );
	else m_TileDesign.SetForeColor( m_SelColor.y(), c );
	
	SetTileDesign();	
}

/*
void CScreenW::SetPixelRect( QImage *pImage, int x, int y, uint color, int w, int h )
{
	int r, s;
	QRgb *pPixel;
	
	
	for( s = y; s < y+h; s++ )
	{
		for( r = x, pPixel = ( (QRgb*)pImage->scanLine( s ) + x  ) ; r < x+w; r++, pPixel++ )
		{
			*pPixel = color;
		}
	}

}
*/
void CScreenW::OnTileClickLeft( int x, int y )
{
	x /= 12;
	y /= 12;
	
	if( m_pRadBack->isChecked() ) 
	{
		m_TileDesign.SetBackPixel( x, y );
		m_SelColor = QPoint( 0, y );
	}
	else 
	{
		m_TileDesign.SetForePixel( x, y );
		m_SelColor = QPoint( 1, y );
	}
	 
	SetTileDesign();
}

void CScreenW::OnTileClickRight( int x, int y )
{
	 x /= 12;
	 y /= 12;
	 
	 if( !m_pRadBack->isChecked() ) m_TileDesign.SetBackPixel( x, y );
	 else m_TileDesign.SetForePixel( x, y );
	 
	 SetTileDesign();
}

void CScreenW::OnFromBank()
{
	CopyToTileDesign( m_SelTile.x(), m_SelTile.y() );
}

void CScreenW::OnToBank()
{
	m_TilesBank[ m_SelTile.x() ][ m_SelTile.y() ] = m_TileDesign;
	UpdateBank( m_SelTile.x(), m_SelTile.y() );
}

void CScreenW::OnScreenClick( int x, int y )
{
	x = x / 16;
	y = y / 16;
	
	if( ( y / 8 ) != m_SelTile.y() ) return;
	
	m_Screen[y*32+x] = m_SelTile.x();
	
	UpdateScreen();
}

void CScreenW::OnBankChanged( int index )
{
	OnBankClick( ( m_SelTile.x() % 32 )*18, ( m_SelTile.x() / 32 )*18, index );
}

void CScreenW::CopyToTileDesign( int index, int bank )
{
	m_TileDesign = m_TilesBank[index][bank];
	SetTileDesign();
}

void CScreenW::SetTileDesign()
{
	int y;
	QImage image;
	
	
	image = QImage( 96, 96, QImage::Format_RGB32 );
	
	PaintTile( &image, m_TileDesign, 0, 0, 12 );

	m_pLblTile->put_Image( image );
	
	image = QImage( 42, 98, QImage::Format_RGB32 );

	for( y = 0; y < 8; y++ )
	{
		CSupportFuncs::SetPixelRect( &image, 0, y*12, CSupportFuncs::COLORS_TABLE[m_TileDesign.GetBgColor( y )], 20, 12 );
		CSupportFuncs::SetPixelRect( &image, 20, y*12, CSupportFuncs::COLORS_TABLE[m_TileDesign.GetForeColor( y )], 20, 12 );
		
		CSupportFuncs::SetBorderImage( &image, 0, y*12, 20, 12, 0xC0C0C0 );
		CSupportFuncs::SetBorderImage( &image, 20, y*12, 20, 12, 0xC0C0C0 );
	}
	m_pLblPalette->put_Image( image );
		
}

void CScreenW::PaintTile( QImage *pImage, CTile &tile, int posX, int posY, int dotSize )
{
	int x, y;
	
	
	for( y = 0; y < 8; y++ )
	{
		for( x = 0; x < 8; x++ )
		{
			CSupportFuncs::SetPixelRect( pImage, posX + x*dotSize, posY + y*dotSize, CSupportFuncs::COLORS_TABLE[tile.GetPixelColor( x, y )], dotSize, dotSize );
		}
	}
}

void CScreenW::PaintGrid( QImage *pImage, int gridWidth, int gridHeight )
{
	int i, j;
	
	
	for( i = 1; i < pImage->height(); i+= ( gridHeight+ 2 ) )
	{
		for( j = 0; j < pImage->width(); j++ ) 
		{
			pImage->setPixel( j, i-1, 0xC0C0C0 );	
			pImage->setPixel( j, i+gridHeight, 0xC0C0C0 );	
		}
	}
	
	for( i = 1; i < pImage->width(); i+= ( gridWidth + 2 ) )
	{
		for( j = 0; j < pImage->height(); j++ ) 
		{
			pImage->setPixel( i-1, j, 0xC0C0C0 );	
			pImage->setPixel( i+gridWidth, j, 0xC0C0C0 );	
		}
	}
	

}
/*
void CScreenW::SetBorderImage( QImage *pImage, int x, int y, int w, int h, int color )
{
	int i;
	

	for( i = x - 1; i < x + w + 1; i++ )
	{
		if( i < 0 || i >= pImage->width() || ( y - 1 ) < 0 || ( y + h ) >= pImage->height() ) continue;

		pImage->setPixel( i, y - 1, color );
		pImage->setPixel( i, y + h, color );
	}
	
	for( i = y -1; i < y + h+ 1; i++ )
	{
		if( ( x -1 ) < 0 || ( x - 1 ) >= pImage->width() || i < 0 || i >= pImage->height() ) continue;

		pImage->setPixel( x - 1, i, color );
		pImage->setPixel( x + w, i, color );
	}

	
}
*/
void CScreenW::OnRadBack()
{
	m_SelColor = QPoint( 0, m_SelColor.y() );
}

void CScreenW::OnRadFore()
{
	m_SelColor = QPoint( 1, m_SelColor.y() );
}

void CScreenW::NewScreen()
{
	int i;
		
	for( i = 0; i < 32*24; i++ ) m_Screen[i] = 0;
	
	UpdateScreen();
}

bool CScreenW::LoadScreen( QString fileName )
{
	int i;
	QString line;
	QFile hFile;
	
	
	hFile.setFileName( fileName );
	hFile.open( QIODevice::ReadOnly );
	QTextStream str( &hFile );

	if( hFile.atEnd() ) 
	{
		hFile.close();
		return false;
	}

	line = str.readLine();

	if( line != "SCREEN" )
	{
		hFile.close();
		return false;
	}

	for( i = 0; i < 32*24; i++ )
	{
		line = str.readLine();
		m_Screen[i] = line.toInt();
	}

	hFile.close();

	UpdateScreen();
	
	return true;
}

bool CScreenW::SaveScreen( QString fileName )
{
	int i;
	QFile hFile;
	

	hFile.setFileName( fileName );
	hFile.open( QIODevice::WriteOnly );

	QTextStream str( &hFile );
	
	str<<"SCREEN"<<endl;
	
	for( i = 0; i < 32*24; i++ ) str<<m_Screen[i]<<endl;

	hFile.flush();
	hFile.close();
	
	return true;
}

bool CScreenW::ExportScreen( QString fileName )
{
	int i;
	QFile hFile;
	

	hFile.setFileName( fileName );
	hFile.open( QIODevice::WriteOnly );

	QTextStream str( &hFile );
	
	str<<"SCREEN:"<<endl<<"db ";
	
	for( i = 0; i < 256*3; i++ ) 
	{
		str<<m_Screen[i];
		
		if( (i+1)%32 == 0 ) 
		{
			str<<endl;
			if( (i+1) != 256*3 ) str<<"db ";
		}
		else str<<", ";
	}
	
	hFile.flush();
	hFile.close();
	
	return true;
}

void CScreenW::NewTiles()
{
	int b, i;
	
	for( b = 0; b < 3; b++ )
	{
		for( i = 0; i < 256; i++ ) m_TilesBank[i][b] = CTile();
	}
	InitBanks();
}

bool CScreenW::LoadTiles( QString fileName )
{
	int i;
	int x, y, b;
	QString line;
	QFile hFile;
	
	
	hFile.setFileName( fileName );
	hFile.open( QIODevice::ReadOnly );
	QTextStream str( &hFile );

	if( hFile.atEnd() ) 
	{
		hFile.close();
		return false;
	}
	
	if( str.readLine() != "TILES" )
	{
		hFile.close();
		return false;
	}

	for( b = 0; b < 3; b++ )
	{
		line = str.readLine();

		if( line != QString( "BANK%1" ).arg( b ) )
		{
			hFile.close();
			return false;
		}
		for( i = 0; i < 256; i++ )
		{
			for( y = 0; y < 8; y++ ) m_TilesBank[i][b].put_BgColor( y, str.readLine().toInt() );
			
			for( y = 0; y < 8; y++ ) m_TilesBank[i][b].put_ForeColor( y, str.readLine().toInt() );
			
			for( y = 0; y < 8; y++ )
			{
				for( x = 0; x < 8; x++ ) m_TilesBank[i][b].put_Pixel( x, y, str.readLine().toInt() );
			}
		}
	}

	hFile.close();
	
	InitBanks();

	return true;
}

bool CScreenW::SaveTiles( QString fileName )
{
	int i, b;
	int x, y;
	QFile hFile;
	

	hFile.setFileName( fileName );
	hFile.open( QIODevice::WriteOnly );

	QTextStream str( &hFile );
	
	str<<"TILES"<<endl;
	
	for( b = 0; b < 3; b++ )
	{
		str<<"BANK"<<b<<endl;
		
		for( i = 0; i < 256; i++ )
		{
			for( x = 0; x < 8; x++ ) str<<m_TilesBank[i][b].get_BgColor(x)<<endl;
			for( x = 0; x < 8; x++ ) str<<m_TilesBank[i][b].get_ForeColor(x)<<endl;
			for( y = 0; y < 8; y++ )
			{
				for( x = 0; x < 8; x++ ) str<<m_TilesBank[i][b].get_Pixel( x, y )<<endl;
			}
		}
	}
	
	hFile.flush();
	hFile.close();
	
	return true;
}

bool CScreenW::ExportTiles( QString fileName )
{
	int i, j;
	int b;
	QFile hFile;
	

	hFile.setFileName( fileName );
	hFile.open( QIODevice::WriteOnly );

	QTextStream str( &hFile );
	
	for( b = 0; b < 3; b++ )
	{
		str<<QString( "BANK_PATTERN_%1:").arg( b )<<endl;

		for( j = 0; j < 256; j++ )
		{
			str<<"db ";
			
			for( i = 0; i < 8; i++ ) 
			{
				str<<m_TilesBank[j][b].GetRowPattern( i );
				if( i != 7 ) str<<", ";
			}
			str<<endl;
		}
	}
	
	str<<endl<<endl;
	
	for( b = 0; b < 3; b++ )
	{
		str<<QString( "BANK_COLOR_%1:").arg( b )<<endl;

		for( j = 0; j < 256; j++ )
		{
			str<<"db ";
			for( i = 0; i < 8; i++ ) 
			{
				str<<m_TilesBank[j][b].GetRowColor( i );
				if( i != 7 ) str<<", ";
			}
			str<<endl;
		}
	}
	
	hFile.flush();
	hFile.close();
	
	return true;
}

void CScreenW::Close()
{
	m_Close = true;
	close();
}

void CScreenW::closeEvent( QCloseEvent *pEvent )
{
	if( m_Close ) pEvent->accept();
	else pEvent->ignore();
}
